/******************************************************************************
 *
 * @copyright:          Copyright 2011 UniSky Ltd.
 * @file:
 * @author:              kenping.liu
 * @creation:
 * @description:
 *
 * @modifications
 * date         user                description
 *
 *
 * @more-details
 *
 *****************************************************************************/
#ifndef _UNISKY_INC_H_
#define _UNISKY_INC_H_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef _U_INC_
#   define _U_INC_
#endif

#include "u_config.h"

//
//  Public Includes
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <locale>
#include <string>
#include <list>
#include <vector>
#include <deque>
#include <map>
#include <sstream>
#include <fstream>
#include <exception>
#include <iostream>
#include <algorithm>
#include <typeinfo>
#include <cctype>

//
//  Platform includes
//

#if defined(WINDOWS)

#   if !defined(_WINSOCK2API_)
#       include <winsock2.h>
#       define _WINSOCK2API_
#   endif

#   if !defined(_INC_WINDOWS)
#       include <windows.h>
#       define _INC_WINDOWS
#endif

#   include <process.h>
#   include <io.h>
#   include <shlwapi.h>
#   include <iphlpapi.h>
#   include <tchar.h>
#   include <ws2spi.h>
#   include <shellapi.h>
#   include <tlhelp32.h>
#   include <psapi.h>
#   include <WinInet.h>

#   pragma comment(lib, "ws2_32.lib")
#   pragma comment(lib, "shlwapi.lib")
#   pragma comment(lib, "iphlpapi.lib")
#   pragma comment(lib, "psapi.lib")
#   pragma comment(lib, "Wininet.lib")

//#define USE_CURL_ALWAYS 1

#elif defined(LINUX)

#   include <dlfcn.h>
#   include <fcntl.h>
#   include <ifaddrs.h>
#   include <netdb.h>
#   include <pthread.h>
#   include <signal.h>
#   include <unistd.h>
#   include <wchar.h>
#   include <iconv.h>
#   include <errno.h>

#   include <arpa/inet.h>

#   include <netinet/in.h>
#   include <netinet/ip.h>
#   include <netinet/tcp.h>

#if 0
#   include <linux/if.h>
#   include <linux/if_ether.h>
#   include <linux/if_packet.h>
#endif

#   include <sys/ioctl.h>
#   include <sys/sendfile.h>
#   include <sys/socket.h>
#   include <sys/time.h>
#   include <sys/timeb.h>
#   include <sys/uio.h>
#   include <sys/resource.h>

#endif

#if defined(USE_CURL_ALWAYS)
// libcurl
#   include <curl/curl.h>
//#   include <curl/types.h>
#   include <curl/easy.h>

#   if defined(WINDOWS)
#   if defined(U_DEBUG)
#       pragma comment(lib, "curllib_static_d.lib")
#   else
#       pragma comment(lib, "curllib_static.lib")
#   endif
#   endif
#endif


#if !defined(NO_ERROR)
#   define NO_ERROR 0
#endif

#define U_NAMESPACE_BEGIN(x)  namespace x {
#define U_NAMESPACE_END(x)    }
#define U_NAMESPACE_ALIAS(alias, long_name) namespace alias=long_name

#define MAX_NAME_LEN        128
#define MAX_ARRAY_LEN       32
#if !defined(MAX_PATH)
#   define MAX_PATH         260
#endif

#if !defined(WINDOWS)
typedef unsigned int        UINT;
typedef unsigned char       UCHAR;
typedef unsigned char       BYTE;
typedef unsigned short      USHORT;
typedef unsigned int        UINT32;
typedef unsigned short      WORD;
typedef unsigned long       DWORD;
typedef unsigned long long  UINT64;

#if defined(U_UNICODE)
typedef wchar_t TCHAR;
#define _T(x)   L##x
#else
typedef char    TCHAR;
#define _T(x)   x
#endif

#endif

#if defined(WINDOWS)
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#endif

// function macro
#define u_max(a, b)            (((a) > (b)) ? (a) : (b))
#define u_min(a, b)            (((a) < (b)) ? (a) : (b))
#define u_between(_Left, _Right, _Value)    ( (_Value)>=(_Left) && (_Value)<=(_Right) )

#if !defined(ZeroMemory)
#   define ZeroMemory(_Dst, _Size)    memset((_Dst), 0, (_Size))
#endif

#define u_containts_key(m, k) (m.find(k)!=m.end())

#if defined(WINDOWS)
#   define u_sleep(ms)   ::Sleep(ms)
#else
#   define u_sleep(ms)   ::usleep((ms)*1000)
#endif

#if defined(MSC_2008)
#   define u_sprintf     sprintf_s
#   define u_swprintf    swprintf_s
#   define u_stprintf    _stprintf_s
#   define u_strcpy      strcpy_s
#   define u_strncpy     strncpy_s
#   define u_vsprintf    vsprintf_s
#   else
#   define u_sprintf     sprintf
#   define u_swprintf    swprintf
#   define u_stprintf    _stprintf
#   define u_strcpy      strcpy
#   define u_strncpy     strncpy
#   define u_vsprintf    vsprintf
#endif

#if defined(MSC_2008)
#   define u_stricmp  _stricmp
#elif defined(WINDOWS)
#   define u_stricmp  stricmp
#else
#   define u_stricmp  strcasecmp
#endif

U_NAMESPACE_BEGIN(u)

#if defined(WINDOWS)
#   pragma warning(push)
#   pragma warning(disable:4200)
#endif

// TLV�ṹ
typedef struct _st_tlv_
{
    UINT tag;
    UINT len;
    char value[0];
}TLV;
enum { TLV_V_OFFSET = sizeof(UINT)+sizeof(UINT) };

#if defined(WINDOWS)
#   pragma warning(pop)   // Restore all warnings to the previous state
#endif

template<typename T>
class AutoHeapT
{
public:
    AutoHeapT(size_t length=1024) : _size(0), _head(NULL)
    {
        reset(length);
    }

    ~AutoHeapT()
    {
        if ( NULL!=_head )
        {
            delete[] _head;
        }
	    _head = NULL;
    }

    void reset(size_t length=1024, const T* other=NULL, size_t len=0)
    {
        if ( length > 0 )
        {
            if ( NULL!=_head )
            {
                delete[] _head;
            }

            _length = length;
            _size   = sizeof(T) * _length;

            _head = new T[_length+1];
            zero();

            if ( NULL!=other && len>0 )
            {
                memcpy(_head, other, sizeof(T)*len);
            }
        }
    }

    void zero()
    {
        if ( NULL!=_head )
        {
            ZeroMemory(_head, _size+sizeof(T));
        }
    }

    size_t length()
    {
        return _length;
    }

    size_t size()
    {
        return _size;
    }

    TLV* tlv()
    {
        return (TLV*)_head;
    }

    T* head()
    { 
        return _head;
    }

    T& operator[](size_t idx)
    {
        return _head[idx];
    }

    operator T*()
    {
        return _head;
    }

    template<typename TT>
    operator TT* ()
    { 
        return (TT*)_head;
    }

private:
    size_t  _length;
    size_t  _size;
    T*      _head;
};

typedef AutoHeapT<char>     AutoHeap;
typedef AutoHeapT<char>     AutoHeapA;
typedef AutoHeapT<wchar_t>  AutoHeapW;

TCHAR* get_error_msg(long err_code=0);

U_NAMESPACE_END(u)

#endif
